package com.klikmee.sms.core.base;

import java.text.MessageFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.log4j.Logger;

import com.klikmee.sms.core.base.communicator.Communicator;
import com.klikmee.sms.core.base.communicator.DeliveryReport;
import com.klikmee.sms.core.base.communicator.SendSmsIntercepter;
import com.klikmee.sms.core.base.creators.MessageCreator;
import com.klikmee.sms.core.base.dao.BulkMessageDAO;
import com.klikmee.sms.core.base.dao.IncomingMessageFacadeLocal;
import com.klikmee.sms.core.base.dao.OutgoingMessageFacadeLocal;
import com.klikmee.sms.core.base.dao.ServiceDAO;
import com.klikmee.sms.core.base.exceptions.CommunicatorNotResolvedException;
import com.klikmee.sms.core.base.postman.ServiceMessageDeliverer;
import com.klikmee.sms.core.base.resolvers.IncomingMessage2ServiceResolver;
import com.klikmee.sms.core.base.util.Constants;
import com.klikmee.sms.core.base.util.States;
import com.klikmee.sms.core.commons.events.EventDispatcher;
import com.klikmee.sms.core.commons.exceptions.ExceptionHandler;
import com.klikmee.sms.core.commons.queues.EnqueueItemException;
import com.klikmee.sms.core.commons.queues.QueueItem;
import com.klikmee.sms.core.commons.queues.QueueManager;
import com.klikmee.sms.core.model.BulkMessage;
import com.klikmee.sms.core.model.IncomingMessage;
import com.klikmee.sms.core.model.OutgoingMessage;
import com.klikmee.sms.core.model.Provider;
import com.klikmee.sms.core.model.Service;
import com.klikmee.sms.core.model.ServiceChargingCategory;

public class Core {
	/**
	 * Instance of log
	 */
	private Logger															logger									= Logger.getLogger( Core.class );
	/**
	 * Dao instances
	 */
	private OutgoingMessageFacadeLocal										outgoingMessageDAO						= null;
	private IncomingMessageFacadeLocal										incomingMessageDAO						= null;
	private ServiceDAO														serviceDAO								= null;
	private BulkMessageDAO													bulkMessageDAO							= null;

	/**
	 * Message creator used to create charged and bulk messages
	 */
	private MessageCreator													messageCreator							= null;
	/**
	 * Component responsible for delivering messages, status reports and
	 * subscription events to service instances
	 */
	private ServiceMessageDeliverer											messageDeliverer						= null;

	/**
	 * Cached list off all services for better performance
	 */
	private List<Service>													serviceDefinitions						= null;

	/**
	 * Service instance used in situations when customer needs to be notified
	 * free of charge
	 */
	private Service															freeOfChargeService						= null;
	private String															notEngoughCreditMessageText				= null;
	private String															serviceNotAvailableMessageText			= null;

	/**
	 * Service instance used in situations when customer sends unrecognized
	 * request
	 */
	private Service															badRequestService						= null;
	private String															badSintaxMessageText					= null;
	// misc

	/**
	 * Ids used to load badRequest and freeOfCharge services
	 */
	private Long															badRequestServiceId						= null;
	private Long															freeOfChargeServiceId					= null;

	/**
	 * Queues for buffering incoming, outgoing, bulk and delivery report
	 * messages.
	 */
	private BlockingQueue<IncomingMessage>									incomingMessageQueue					= new LinkedBlockingQueue<IncomingMessage>();
	private BlockingQueue<OutgoingMessage>									outgoingMessageQueue					= new LinkedBlockingQueue<OutgoingMessage>();
	private BlockingQueue<BulkMessage>										bulkMessageQueue						= new LinkedBlockingQueue<BulkMessage>();

	/**
	 * Delivery report queue manager
	 */
	private QueueManager<DeliveryReport>									deliveryReportQueueManager;
	// number of minutes delivery report is valid from it's reception
	private int																deliveryReportValidityInMinutes;
	/**
	 * Cache instances
	 */

	private Map<String, OutgoingMessage>									outgoingMessageCache;

	/**
	 * Cache drivers
	 */

	private Map<String, CoreCacheDriver<DeliveryReport, OutgoingMessage>>	outgoingMessageDriverMap;
	/**
	 * Worker threads for queue processing.
	 */
	private Thread															incommingMessageQueueProcessingThread	= null;
	private Thread															outgoingMessageQueueProcessingThread	= null;
	private Thread															bulkMessageQueueProcessingThread		= null;

	/**
	 * Exception handler used to handler internal, service and other errors
	 */
	private ExceptionHandler												exceptionHandler						= null;
	/**
	 * Map of communicators configured for this instance of core context. Key is
	 * the name of the communicator identical to the value of
	 * {@link Provider#getName()} of the provider the communicator is
	 * implemented for. The value is and instance of communicator for that
	 * provider. Example: for MTS communicator value is MTS for VIP is VIP and
	 * so on The names of each implemented communicator can be found in
	 * {@link Constants} class.
	 * 
	 */
	private Map<String, Communicator>										communicatorMap							= null;

	/**
	 * Map of incoming message resolvers used to resolve incoming message to
	 * service definition
	 */
	private Map<String, IncomingMessage2ServiceResolver>					incomingMessageResolverMap				= null;

	/**
	 * Flag indicating that is time to stop queue processing.
	 */
	private boolean															stopQueueProcessing						= false;
	/**
	 * Event dispatcher for core events
	 */
	private EventDispatcher													eventDispatcher;

	/**
	 * Default constructor for core context
	 */
	public Core() {
	}

	/**
	 * Init method for initializing core resources
	 */
	public void init() {
		// cache all service definitions
		loadServicesDefinitions();
		// start all worker threads
		this.startQueueProcessingThreads();
		
		// start delivery report queue manager
		this.deliveryReportQueueManager.start();
		
		logger.info( MessageFormat.format( "Mapped {0} communicators instances", communicatorMap.size() ) );
		logger.info( MessageFormat.format( "Mapped {0} incoming message resolvers", incomingMessageResolverMap.size() ) );

		logger.info( "Core initialized. " );
	}

	/**
	 * Enqueues incoming message for processing.
	 * <p>
	 * Usually called from {@link Communicator} implementation
	 * </p>
	 * 
	 * @param incomingMessage
	 */
	public void enqueueIncomingMessage(IncomingMessage incomingMessage) {
		try {
			incomingMessageQueue.put( incomingMessage );
			logger.debug( MessageFormat.format( "Enqueued new incomming message from [{0}], current queue size [{1}]", incomingMessage.getFromNumber(), incomingMessageQueue.size() ) );
		}
		catch (InterruptedException e) {
			logger.fatal( "Interupted while waiting to enqueue incoming message. ", e );
		}
		catch (Exception e) {
			exceptionHandler.handle( e );
		}
	}

	/**
	 * Enqueues new message to the outgoing queue.
	 * 
	 * @param outgoingMessage
	 *            a message to be sent
	 */
	public void enqueueOutgoingMessage(OutgoingMessage outgoingMessage) {
		try {
			outgoingMessageQueue.put( outgoingMessage );
			logger.info( MessageFormat.format( "Enqueued outgoing message with id = [{0}]", outgoingMessage.getId() ) );
		}
		catch (InterruptedException e) {
			logger.fatal( "Interupted while waiting to enqueue outgoing message. ", e );
		}
	}

	/**
	 * Adds new bulk message to the tail of the outgoing bulk queue
	 * 
	 * @param bulkMessage
	 */
	public void enqueueBulkMessage(BulkMessage bulkMessage) {
		try {
			this.bulkMessageQueue.put( bulkMessage );
			logger.info( MessageFormat.format( "Enqueued bulk message with id = [{0}]", bulkMessage.getId() ) );
		}
		catch (InterruptedException e) {
			logger.fatal( "Interupted while waiting to enqueue bulk message. ", e );
		}
	}

	/**
	 * Enqueues status report for the send message. Usually called by
	 * communicator.
	 * 
	 * @param deliveryReport
	 */
	public void enqueueStatusReport(DeliveryReport deliveryReport) {
		// calculate validity period and enqueue delivery report
		QueueItem<DeliveryReport> item = new QueueItem<DeliveryReport>( deliveryReport );
		item.setProcessed( false );
		item.setDiscardedEventType( EventManager.DELIVERY_REPORT_DISCARDED );
		
		Calendar calendar = Calendar.getInstance();
		calendar.add( Calendar.MINUTE, this.deliveryReportValidityInMinutes );
		item.setValidTo( calendar.getTime() );

		try {
			this.deliveryReportQueueManager.enqueue( item );
			logger.info( MessageFormat.format( "Enqueued new status report {0}", item ) );
		}
		catch (EnqueueItemException e) {
			logger.fatal( MessageFormat.format( "Error while trying to enqueue {0}", item ), e );
		}
	}

	/**
	 * Processes an incoming message from the queue by calling
	 * {@link #onNewMessage(IncomingMessage)} method
	 */
	public void processIncomingMessageQueue() {

		try {

			IncomingMessage incomingMessage = incomingMessageQueue.take();
			logger.debug( MessageFormat.format( "Took incoming message from sender [{0}] from queue", incomingMessage.getFromNumber() ) );

			this.onNewMessage( incomingMessage );

		}
		catch (InterruptedException e) {
			logger.fatal( "Interupted while waiting to process incoming messages ", e );
		}
		catch (Exception e) {
			exceptionHandler.handle( e );
		}
	}

	/**
	 * Takes next message from the outgoing queue and calls
	 * {@link #forwardToCommunicator(OutgoingMessage)} with the message as an
	 * argument.
	 */
	public void processOutgoingMessageQueue() {

		try {

			// take message from queue and cache it
			OutgoingMessage outgoingMessage = outgoingMessageQueue.take();
			logger.debug( MessageFormat.format( "Took outgoing message with id = [{0}] from queue", outgoingMessage.getId() ) );

			this.forwardToCommunicator( outgoingMessage );
		}
		catch (InterruptedException e) {
			logger.fatal( "Interupted while waiting to process outgoing messages ", e );
		}
		catch (Exception e) {
			exceptionHandler.handle( e );
		}

	}

	/**
	 * Takes next bulk message from queue and forwards it to the resolved
	 * communicator
	 */
	public void processBulkMessageQueue() {

		try {

			BulkMessage bulkMessage = bulkMessageQueue.take();

			logger.debug( MessageFormat.format( "Took bulk message with id = [{0}] from queue", bulkMessage.getId() ) );
			forwardToCommunicator( bulkMessage );
		}
		catch (InterruptedException e) {
			logger.fatal( "Interupted while waiting to process bulk messages ", e );
		}
		catch (Exception e) {
			logger.fatal( "Unexpected error while processing bulk queue ", e );
		}
	}

	/**
	 * Forwards bulk message to appropriate communicator
	 * 
	 * @param bulkMessage
	 */
	private void forwardToCommunicator(BulkMessage bulkMessage) {
		// resolve communicator
		Provider provider = bulkMessage.getProvider();

		if (provider != null) {
			try {
				Communicator communicator = resolveCommunicator( provider );

				communicator.sendBulkMessage( bulkMessage );

				logger.info( MessageFormat.format( "Bulk message with id = [{0}] forwarded to communicator", bulkMessage.getId() ) );
			}
			catch (CommunicatorNotResolvedException e) {
				exceptionHandler.handle( e );
			}
			catch (Exception e) {
				exceptionHandler.handle( e );
			}
		}
		else {
			logger.warn( MessageFormat.format( "Communicator for bulk message with id = [{0}] and receiver [{1}] could not be resolved", bulkMessage.getId(), bulkMessage.getToNumber() ) );
		}

	}

	/**
	 * Sends the message via appropriate communicator. Communicator is resolved
	 * from {@link #communicatorMap} and each {@link SendSmsIntercepter} for
	 * that communicator is executed. Finaly message is sent by calling
	 * {@link Communicator#sendMessage(OutgoingMessage)} on the resolved
	 * communicator.
	 * 
	 * @param outgoingMessage
	 */
	private void forwardToCommunicator(OutgoingMessage outgoingMessage) {
		// resolve communicator used to send this message
		Communicator communicator = null;
		try {
			communicator = resolveCommunicator( outgoingMessage.getProvider() );

			// execute intercepters assigned to this communicator, if any
			List<SendSmsIntercepter> smsIntercepters = communicator.getSendSmsIntercepters();

			for (SendSmsIntercepter intercepter : smsIntercepters) {
				intercepter.processMessage( outgoingMessage );
			}

			// forward message to communicator
			communicator.sendMessage( outgoingMessage );

			logger.info( MessageFormat.format( "Message with id = [{0}] sent to {1} communicator", outgoingMessage.getId(), communicator ) );
		}
		catch (CommunicatorNotResolvedException e) {
			exceptionHandler.handle( e );
		}
	}

/**
     * callback from {@link #sendMessage(com.klikmee.sms.core.entities.OutgoingMessage)
     * @param outgoingMessage - should be same object as it was in method sendMessage
     * 
     */
	public void onMessageSent(OutgoingMessage outgoingMessage) {
		logger.debug( MessageFormat.format( "OnMessageSent called for message id [{0}], text [{1}]", outgoingMessage.getId(), outgoingMessage.getMessage() ) );

		// resolve cache driver and cache outgoing message
		CoreCacheDriver<DeliveryReport, OutgoingMessage> coreCacheDriver = outgoingMessageDriverMap.get( outgoingMessage.getProvider().getName() );
		coreCacheDriver.write( outgoingMessage );

		// set outgoing message state
		outgoingMessage.setState( States.OutgoingMessage.SENT );
		outgoingMessage.setOurOutGoingTime( new Date() );
		outgoingMessageDAO.edit( outgoingMessage );

		// remove message from cache
		coreCacheDriver.remove( outgoingMessage );

		logger.info( String.format( "Updated message state, msg id [%s]", outgoingMessage.getId() ) );
	}

	/**
	 * Invoked by some of the communicators after successfully sending message.
	 * 
	 * @param bulkMessage
	 *            bulk message sent by communicator.
	 */

	public void onBulkMessageSent(BulkMessage bulkMessage) {
		// just update state
		bulkMessage.setState( States.BulkMessage.SENT );
		bulkMessage.setSendingTime( new Date() );

		bulkMessageDAO.edit( bulkMessage );
	}

	/**
	 * Callback from communicator when it receives new message. This method
	 * links the message to the service based on it's syntax. If massage has a
	 * wrong syntax it is linked to bad request service.
	 * 
	 * @param sms
	 * 
	 */
	public void onNewMessage(IncomingMessage incomingMessage) {
		logger.info( MessageFormat.format( "Received new message request from [{0}], to [{1}], message [{2}]", incomingMessage.getFromNumber(), incomingMessage.getToNumber(),
				incomingMessage.getMessage() ) );

		// resolve service for this message
		Provider provider = incomingMessage.getProvider();
		IncomingMessage2ServiceResolver incomingMessage2ServiceResolver = incomingMessageResolverMap.get( provider.getName() );

		Service resolvedService = incomingMessage2ServiceResolver.resolve( incomingMessage );

		// if message could not be resolve to any service link message to the
		// bad request service and send info message
		// back to the user
		if (resolvedService == null) {
			incomingMessage.setService( badRequestService );
			incomingMessage.setState( States.IncommingMessage.BAD_SYNTAX_NOTIFICATION_SENT );
			incomingMessageDAO.create( incomingMessage );

			ServiceChargingCategory serviceChargingCategory = getBadRequestService().getServiceChargingCategoryList().iterator().next();
			messageCreator.createResponse( incomingMessage, serviceChargingCategory, badSintaxMessageText );

			logger.info( MessageFormat.format( "Could not resolve message to the service, user notification sent, message id = [{0}]", incomingMessage.getId() ) );
		}

		// if service for this message is resolved,
		// forward the message to the concrete service instance
		else {
			incomingMessage.setService( resolvedService );
			incomingMessage.setState( States.IncommingMessage.SYNTACTICALLY_OK );
			incomingMessageDAO.create( incomingMessage );

			// try to deliver message to service
			boolean messageDelivered = false;
			try {
				messageDelivered = messageDeliverer.deliverMessage( incomingMessage );
			}
			catch (Exception e) {

				exceptionHandler.handle( e );
			}

			if (!messageDelivered) {
				// if message is not delivered to service, send info message to
				// user

				messageCreator.createResponse( incomingMessage, this.getFreeOfChargeService().getServiceChargingCategoryList().iterator().next(), this.serviceNotAvailableMessageText );
				// and set im state
				incomingMessage.setState( States.IncommingMessage.SERVICE_NOT_AVAILABLE_NOTIFICATION_SENT );
				incomingMessageDAO.edit( incomingMessage );

				logger.info( MessageFormat.format( "Could not deliver message to service named [{0}], message id = [{1}], user notification sent.", incomingMessage.getService().getName(),
						incomingMessage.getId() ) );
			}

		}

	}

	
	/**
	 * Resolves an instance of concrete communicator from
	 * {@link #communicatorMap} to be used to send outgoing message. Matching is
	 * done using {@link Provider#getName()} attached to the outgoing message
	 * 
	 * @param provider
	 *            the actual message to be sent
	 * @return an instance of {@link Communicator} used to send the message, or
	 *         null if no communicator could be resolved
	 * @throws CommunicatorNotResolvedException
	 */
	private Communicator resolveCommunicator(Provider provider) throws CommunicatorNotResolvedException {

		// get the name of provider associated with this message
		String providersName = provider.getName();

		// use this value to get instance of communicator from the map
		Communicator communicator = this.communicatorMap.get( providersName );

		if (communicator == null) {
			throw new CommunicatorNotResolvedException( MessageFormat.format( "Failed to resolve communicator for message id = [{0}] by providers name = {1}", provider.getId(), providersName ) );
		}

		logger.info( MessageFormat.format( "Resolved communicator instance for provider [{0}]", provider.getName() ) );
		return communicator;
	}

	/**
	 * Starts threads for queue processing
	 */
	private void startQueueProcessingThreads() {
		// incoming message queue

		this.incommingMessageQueueProcessingThread = new Thread( new Runnable() {

			public void run() {
				while (!stopQueueProcessing) {
					Core.this.processIncomingMessageQueue();
				}

			}
		} );

		this.incommingMessageQueueProcessingThread.start();
		logger.info( MessageFormat.format( "Started processing incoming message queue, thread name [{0}]", incommingMessageQueueProcessingThread.getName() ) );

		// outgoing message queue
		this.outgoingMessageQueueProcessingThread = new Thread( new Runnable() {

			public void run() {
				while (!stopQueueProcessing) {
					Core.this.processOutgoingMessageQueue();
				}

			}
		} );

		this.outgoingMessageQueueProcessingThread.start();
		logger.info( MessageFormat.format( "Started processing outgoing message queue, thread name [{0}]", outgoingMessageQueueProcessingThread.getName() ) );

		this.bulkMessageQueueProcessingThread = new Thread( new Runnable() {

			public void run() {
				while (!stopQueueProcessing) {
					Core.this.processBulkMessageQueue();
				}

			}
		} );

		this.bulkMessageQueueProcessingThread.start();
		logger.info( MessageFormat.format( "Started processing bulk message queue, thread name [{0}]", bulkMessageQueueProcessingThread.getName() ) );
	}

	/*
	 * utility method for loading service definitions from db. Loads all
	 * services plus bad request and free of charge service.
	 */
	public void loadServicesDefinitions() {

		badRequestService = serviceDAO.find( this.badRequestServiceId );
		logger.debug( MessageFormat.format( "Loaded [{0}] service from database", badRequestService != null ? badRequestService.getName() : "Failed" ) );
		freeOfChargeService = serviceDAO.find( this.freeOfChargeServiceId );
		logger.debug( MessageFormat.format( "Loaded [{0}] service from database", freeOfChargeService != null ? freeOfChargeService.getName() : "Failed" ) );

		// load all service definitions
		this.serviceDefinitions = serviceDAO.findAllPrioritized();
		logger.info( MessageFormat.format( "Loaded {0} service definitions", serviceDefinitions.size() ) );
	}

	public void destroy() {
		stopQueueProcessing = true;
		// interupt the threads
		this.incommingMessageQueueProcessingThread.interrupt();
		this.outgoingMessageQueueProcessingThread.interrupt();
		this.bulkMessageQueueProcessingThread.interrupt();
		
		// stop delivery report queue manager
		this.deliveryReportQueueManager.stop();

		logger.info( "Shuting down core completed." );
	}

	public List<Service> getServiceDefinitions() {
		return serviceDefinitions;
	}

	public Service getFreeOfChargeService() {
		return freeOfChargeService;
	}

	public Service getBadRequestService() {
		return badRequestService;
	}

	public void setOutgoingMessageDAO(OutgoingMessageFacadeLocal outgoingMessageDAO) {
		this.outgoingMessageDAO = outgoingMessageDAO;
	}

	public String getNotEngoughCreditMessageText() {
		return notEngoughCreditMessageText;
	}

	public void setServiceDAO(ServiceDAO serviceDAO) {
		this.serviceDAO = serviceDAO;
	}

	public void setMessageCreator(MessageCreator billing) {
		this.messageCreator = billing;
	}

	public void setIncomintMessageDAO(IncomingMessageFacadeLocal incomintMessageDAO) {
		this.incomingMessageDAO = incomintMessageDAO;
	}

	public void setMessageDeliverer(ServiceMessageDeliverer messageDeliverer) {
		this.messageDeliverer = messageDeliverer;
	}

	public void setBadSintaxMessageText(String badSintaxMessageText) {
		this.badSintaxMessageText = badSintaxMessageText;
	}

	public void setServiceNotAvailableMessageText(String serviceNotAvailableMessageText) {
		this.serviceNotAvailableMessageText = serviceNotAvailableMessageText;
	}

	public void setBulkMessageDAO(BulkMessageDAO bulkMessageDAO) {
		this.bulkMessageDAO = bulkMessageDAO;
	}

	public void setNotEngoughCreditMessageText(String notEngoughCreditMessageText) {
		this.notEngoughCreditMessageText = notEngoughCreditMessageText;
	}

	public String getBadSintaxMessageText() {
		return badSintaxMessageText;
	}

	public OutgoingMessageFacadeLocal getOutgoingMessageDAO() {
		return outgoingMessageDAO;
	}

	public IncomingMessageFacadeLocal getIncomingMessageDAO() {
		return incomingMessageDAO;
	}

	public BulkMessageDAO getBulkMessageDAO() {
		return bulkMessageDAO;
	}

	public MessageCreator getMessageCreator() {
		return messageCreator;
	}

	public ServiceMessageDeliverer getMessageDeliverer() {
		return messageDeliverer;
	}

	public String getServiceNotAvailableMessageText() {
		return serviceNotAvailableMessageText;
	}

	public Logger getLogger() {
		return logger;
	}

	public BlockingQueue<IncomingMessage> getIncomingMessageQueue() {
		return incomingMessageQueue;
	}

	public BlockingQueue<OutgoingMessage> getOutgoingMessageQueue() {
		return outgoingMessageQueue;
	}

	public BlockingQueue<BulkMessage> getBulkMessageQueue() {
		return bulkMessageQueue;
	}

	public Thread getIncommingMessageQueueProcessingThread() {
		return incommingMessageQueueProcessingThread;
	}

	public Thread getOutgoingMessageQueueProcessingThread() {
		return outgoingMessageQueueProcessingThread;
	}

	public Thread getBulkMessageQueueProcessingThread() {
		return bulkMessageQueueProcessingThread;
	}

	public boolean isStopQueueProcessing() {
		return stopQueueProcessing;
	}

	public Long getBadRequestServiceId() {
		return badRequestServiceId;
	}

	public void setBadRequestServiceId(Long badRequestServiceId) {
		this.badRequestServiceId = badRequestServiceId;
	}

	public Long getFreeOfChargeServiceId() {
		return freeOfChargeServiceId;
	}

	public void setFreeOfChargeServiceId(Long freeOfChargeServiceId) {
		this.freeOfChargeServiceId = freeOfChargeServiceId;
	}

	public void setExceptionHandler(ExceptionHandler exceptionHandler) {
		this.exceptionHandler = exceptionHandler;
	}

	public void setCommunicatorMap(Map<String, Communicator> communicatorMap) {
		this.communicatorMap = communicatorMap;
	}

	public void setIncomingMessageResolverMap(Map<String, IncomingMessage2ServiceResolver> incomingMessageResolverMap) {
		this.incomingMessageResolverMap = incomingMessageResolverMap;
	}

	public Map<String, Communicator> getCommunicatorMap() {
		return communicatorMap;
	}

	public void setEventDispatcher(EventDispatcher eventDispatcher) {
		this.eventDispatcher = eventDispatcher;
	}

	public EventDispatcher getEventDispatcher() {
		return eventDispatcher;
	}

	public void setOutgoingMessageCache(Map<String, OutgoingMessage> outgoingMessageCache) {
		this.outgoingMessageCache = outgoingMessageCache;
	}

	public Map<String, OutgoingMessage> getOutgoingMessageCache() {
		return outgoingMessageCache;
	}

	public void setOutgoingMessageDriverMap(Map<String, CoreCacheDriver<DeliveryReport, OutgoingMessage>> outgoingMessageDriverMap) {
		this.outgoingMessageDriverMap = outgoingMessageDriverMap;
	}

	public void setDeliveryReportQueueManager(QueueManager<DeliveryReport> deliveryReportQueueManager) {
		this.deliveryReportQueueManager = deliveryReportQueueManager;
	}

	public void setDeliveryReportValidityInMinutes(int deliveryReportValidityInMinutes) {
		this.deliveryReportValidityInMinutes = deliveryReportValidityInMinutes;
	}
}
